package com.sls.game.supply.deal;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.sls.core.common.CommonUtil;
import com.sls.core.http.HttpClient;
import com.sls.core.socket.Head;
import com.sls.core.util.PropertiesUtil;
import com.sls.core.util.ServerDateAndTime;
import com.sls.core.util.UtilMD5Encryption;
import com.sls.game.common.DeductionRefund;
import com.sls.game.dao.DownstreamUserDAO;
import com.sls.game.dao.GoodsOrderDAO;
import com.sls.game.dao.xinhe.XinHeAccountDAO;
import com.sls.game.dao.xinhe.XinHeChargeUnitDAO;
import com.sls.game.dao.xinhe.XinHeGameDAO;
import com.sls.game.dao.xinhe.XinHeGameGiftDAO;
import com.sls.game.dao.xinhe.XinHeProductDAO;
import com.sls.game.parser.ParseXinHeXml;
import com.sls.game.pojo.DeductionRefundInfo;
import com.sls.game.pojo.GoodsOrderInfo;
import com.sls.game.pojo.SLSHttpInterfaceInfo;
import com.sls.game.pojo.xinhe.XinHeAccount;
import com.sls.game.pojo.xinhe.XinHeChargeUnit;
import com.sls.game.pojo.xinhe.XinHeGame;
import com.sls.game.pojo.xinhe.XinHeGameGift;
import com.sls.game.pojo.xinhe.XinHeProduct;
import com.sls.game.pojo.xinhe.XinHeRespInfo;

@Service("xinHeTradeDeal")
public class XinHeTradeDeal {

	private static Logger log = Logger.getLogger(XinHeTradeDeal.class);
	private static String filename = "xinhe.properties";

	@Resource(name = "xinHeProductDAO")
	private XinHeProductDAO productDao;
	@Resource(name = "xinHeAccountDAO")
	private XinHeAccountDAO accountDao;
	@Resource(name = "xinHeGameDAO")
	private XinHeGameDAO gameDao;
	@Resource(name = "xinHeChargeUnitDAO")
	private XinHeChargeUnitDAO chargeDao;
	@Resource(name = "xinHeGameGiftDAO")
	private XinHeGameGiftDAO giftDao;
	@Resource(name = "downstreamUserDAO")
	private DownstreamUserDAO downstreamUserDAO;
	@Resource(name = "goodsOrderDAO")
	private GoodsOrderDAO goodsOrderDAO;

	public SLSHttpInterfaceInfo getGoodsDetailOfXinHe(
			SLSHttpInterfaceInfo sLSHttpInterfaceInfo, String originalGoodsId) {
		XinHeProduct xhp = this.productDao.queryByProductId(originalGoodsId);
		String companyId = "";
		String numberLimit = "";
		if (xhp != null) {
			companyId = xhp.getCompanyId();
			numberLimit = xhp.getNumberLimit();
		}

		List<XinHeGame> asList = this.gameDao.queryByCompanyId(companyId);
		List<String> bigAreaNameList = this.gameDao
				.queryAreaNameByCompanyId(companyId);
		List<String> rechargeNameList = this.chargeDao
				.queryRechargeNameByCompanyId(companyId);
		List<String> AccNameList = this.accountDao
				.queryAccNameByCompanyId(companyId);

		StringBuilder areaServerName = new StringBuilder();
		StringBuilder rechName = new StringBuilder();
		StringBuilder accName = new StringBuilder();
		StringBuilder sb = new StringBuilder();
		if (bigAreaNameList != null && bigAreaNameList.size() > 0) {
			for (String bigAreaName : bigAreaNameList) {
				if (StringUtils.isNotBlank(bigAreaName)) {
					sb.append(bigAreaName);
					sb.append("&&");
				}
			}
		}
		if (asList != null && asList.size() > 0) {
			for (XinHeGame areaSerInfo : asList) {
				areaServerName.append(areaSerInfo.getAreaName());
				areaServerName.append("##");
				String smallServerName = areaSerInfo.getServerName();
				if (StringUtils.isNotBlank(smallServerName)) {
					areaServerName.append(smallServerName);
				} else {
					areaServerName.append("null");
				}
				areaServerName.append("&&");
			}
		}
		if (rechargeNameList != null && rechargeNameList.size() > 0) {
			for (String reName : rechargeNameList) {
				rechName.append(reName);
				rechName.append("&&");
			}
		}
		if (AccNameList != null && AccNameList.size() > 0) {
			for (String aName : AccNameList) {
				accName.append(aName);
				accName.append("&&");
			}
		}
		String asName = areaServerName.toString();
		String areaNameStr = sb.toString();
		String rechNameStr = rechName.toString();
		String accountNameStr = accName.toString();
		String areaServer = null;
		String bigAreaName = null;
		String recharge = null;
		String account = null;
		if (asName != null && !("".equals(asName))) {
			areaServer = asName.substring(0, asName.length() - 2);
		}
		if (areaNameStr != null && !("".equals(areaNameStr))) {
			bigAreaName = areaNameStr.substring(0, areaNameStr.length() - 2);
		}
		if (rechNameStr != null && !("".equals(rechNameStr))) {
			recharge = rechNameStr.substring(0, rechNameStr.length() - 2);
		}
		if (accountNameStr != null && !("".equals(accountNameStr))) {
			account = accountNameStr.substring(0, accountNameStr.length() - 2);
		}
		StringBuilder strBui = new StringBuilder();
		strBui.append(recharge);
		strBui.append("##");
		if (StringUtils.isNotBlank(numberLimit)) {
			strBui.append(numberLimit);
		} else {
			strBui.append("null");
		}
		strBui.append("##");
		strBui.append("null");
		strBui.append("##");
		strBui.append("null");
		String chargeType = strBui.toString().trim();
		sLSHttpInterfaceInfo.setAccountType(account);
		sLSHttpInterfaceInfo.setChargeType(chargeType);
		sLSHttpInterfaceInfo.setGameServer(areaServer);
		sLSHttpInterfaceInfo.setGameArea(bigAreaName);
		sLSHttpInterfaceInfo.setGameUnit("元");

		return sLSHttpInterfaceInfo;
	}

	public String dealTradeResultOfXinHe(SLSHttpInterfaceInfo info,
			String orderId, String paymentOrderNo, String orderTime,
			String mechantIP, String originalGoodsId, Head head) {
		// 返回给上层对象
		SLSHttpInterfaceInfo sLSHttpInterfaceInfo = new SLSHttpInterfaceInfo();
		XinHeRespInfo resInfo = this.trade(info, orderId, paymentOrderNo,
				orderTime, mechantIP, originalGoodsId, head);
		if (resInfo != null) {

			String orderResult = resInfo.getReturnMsg();
			if ("000".equals(orderResult)) { // 成功
				sLSHttpInterfaceInfo.setResMsg("SUCCESS");
				sLSHttpInterfaceInfo.setPtOrderNo(info.getPtOrderNo());
				sLSHttpInterfaceInfo.setStatus("ORDER_SUCCESS");
				sLSHttpInterfaceInfo.setSupOrderNo(orderId);
			} else if ("010".equals(orderResult) || "020".equals(orderResult)
					|| "100".equals(orderResult) || "403".equals(orderResult)
					|| "500".equals(orderResult)) { // 订单状态处理中
				sLSHttpInterfaceInfo.setResMsg("SUCCESS");
				sLSHttpInterfaceInfo.setFailedCode("209");
				sLSHttpInterfaceInfo.setFailedReason("处理中");
				sLSHttpInterfaceInfo.setPtOrderNo(info.getPtOrderNo());
				sLSHttpInterfaceInfo.setStatus("ORDER_UNDERWAY");
				sLSHttpInterfaceInfo.setSupOrderNo(orderId);
			} else {
				// 失败
				sLSHttpInterfaceInfo.setResMsg("FAILED");
				sLSHttpInterfaceInfo.setFailedCode("208");
				sLSHttpInterfaceInfo.setFailedReason("充值失败");
				sLSHttpInterfaceInfo.setPtOrderNo(info.getPtOrderNo());
				sLSHttpInterfaceInfo.setStatus("ORDER_FAILED");
				sLSHttpInterfaceInfo.setSupOrderNo(orderId);

				GoodsOrderInfo goodsOrderInfo = new GoodsOrderInfo();
				DeductionRefundInfo dedInfo = null;
				String paymentStatus = "";
				// 退款
				dedInfo = DeductionRefund.invokeDeductRefund(info, orderId,
						"1", orderTime, paymentOrderNo, head, goodsOrderDAO);
				if (dedInfo != null) {
					paymentStatus = dedInfo.getPaymentStatus();
				}
				if ("1".equals(paymentStatus)) { // 成功
					goodsOrderInfo.setIsPay("3"); // 退款成功
					// 退款成功，通知下游用户
					DeductionRefund.noticeUserRefundMsg(orderId, dedInfo,
							goodsOrderDAO, downstreamUserDAO, null);

				} else if ("2".equals(paymentStatus)) {
					goodsOrderInfo.setIsPay("2"); // 退款失败
				}
				try {
					// 更新订单
					updateGoodsOrder(orderId, goodsOrderInfo, goodsOrderDAO,
							head);
				} catch (Exception e) {
					log.error("请求ID：" + head.getRequestId() + "根据退款状态更新订单异常！",
							e);
				}
			}
		} else {
			sLSHttpInterfaceInfo.setResMsg("SUCCESS");
			sLSHttpInterfaceInfo.setFailedCode("210");
			sLSHttpInterfaceInfo.setFailedReason("订单存疑");
			sLSHttpInterfaceInfo.setPtOrderNo(info.getPtOrderNo());
			sLSHttpInterfaceInfo.setStatus("ORDER_DUBIOUS");
			sLSHttpInterfaceInfo.setSupOrderNo(orderId);
		}

		sLSHttpInterfaceInfo.setGameAccount(info.getGameAccount());
		sLSHttpInterfaceInfo.setUnitPrice(info.getUnitPrice());
		sLSHttpInterfaceInfo.setBuyNum(info.getBuyNum());
		String totalPrice = info.getTotalPrice();
		sLSHttpInterfaceInfo.setTotalPrice(totalPrice);
		Gson gson = CommonUtil.gson();
		String resultBody = gson.toJson(sLSHttpInterfaceInfo);

		return resultBody;
	}

	private XinHeRespInfo trade(SLSHttpInterfaceInfo info, String orderId,
			String paymentOrderNo, String orderTime, String mechantIP,
			String originalGoodsId, Head head) {
		String address = PropertiesUtil.getValue(
				"xinhe.interface.recharge.address", filename);
		String userId = PropertiesUtil.getValue("xinhe.merchant.id", filename);

		GoodsOrderInfo orderInfo = new GoodsOrderInfo();
		orderInfo.setRegisterAccount(userId);
		updateGoodsOrder(orderId, orderInfo, goodsOrderDAO, head);

		Map<String, String> paraMap = assembleParameterOfTrade(info,
				originalGoodsId, orderId, mechantIP);
		// 发送http请求
		XinHeRespInfo resInfo = sendHttpRequestOfDirectTrade(address, paraMap,
				head);
		// 上游订单结果
		String orderResult = "";
		String msg = "";
		String xinHeOrderId = "";
		String successTime = "";
		String statusRemark = "";
		String remark = "";
		String status = "2";
		if (resInfo != null) {
			// 订单结果
			orderResult = resInfo.getReturnMsg();
			msg = map.get(orderResult);
			xinHeOrderId = resInfo.getXhOrder();
			statusRemark = "订单状态备注：" + msg + "，" + resInfo.getSnapshot();
			remark = "充值总额,面值*充值数量:" + resInfo.getAmount() + ",消费金额, 实际消耗金额:"
					+ resInfo.getCost() + ",帐号余额:" + resInfo.getBalance();
			if ("000".equals(orderResult)) { // 成功
				status = "1";
				successTime = ServerDateAndTime.getNowDateTimeOfFormat();
			} else if ("010".equals(orderResult) || "020".equals(orderResult)
					|| "100".equals(orderResult) || "403".equals(orderResult)
					|| "500".equals(orderResult)) { // 订单状态处理中
				status = "2";
			} else {
				status = "0"; // 失败
			}
		} else {
			status = "3"; // 存疑
		}

		GoodsOrderInfo goodsOrderInfo = new GoodsOrderInfo();
		goodsOrderInfo.setStatus(status);
		goodsOrderInfo.setStatusRemark(statusRemark);
		goodsOrderInfo.setRemark(remark);
		goodsOrderInfo.setSupOrderId(xinHeOrderId);
		goodsOrderInfo.setSupOrderSuccessTime(successTime);

		try {
			// 根据交易返回的结果更新订单表
			updateGoodsOrder(orderId, goodsOrderInfo, goodsOrderDAO, head);
		} catch (Exception e) {
			log.error("请求ID：" + head.getRequestId() + "根据鑫合返回的结果更新订单异常！", e);
		}
		return resInfo;

	}

	private void updateGoodsOrder(String orderId,
			GoodsOrderInfo goodsOrderInfo, GoodsOrderDAO goodsOrderDAO,
			Head head) {
		goodsOrderInfo.setOrderId(orderId);
		goodsOrderInfo.setSynOrAsy("0"); // 同步通知标识
		// 数据更新
		try {
			goodsOrderDAO.update(goodsOrderInfo);
		} catch (Exception e) {
			log.error(
					"updateGoodsOrder处理[" + head.getRequestId() + "]的请求出现异常！",
					e);
		}
	}

	private XinHeRespInfo sendHttpRequestOfDirectTrade(String address,
			Map<String, String> map, Head head) {
		XinHeRespInfo resInfo = null;
		HttpClient httpClient = new HttpClient();
		try {
			log.info("请求ID：" + head.getRequestId() + "，发送到鑫合的直充请求参数为："
					+ address + map);
			String str = httpClient.doPost(address, map);
			log.info("请求ID：" + head.getRequestId() + "，鑫合直充返回的结果参数为：" + str);
			if (StringUtils.isNotEmpty(str)) {
				resInfo = ParseXinHeXml.getReturnOfXinHe(str);
			}
		} catch (Exception e) {
			log.error("请求ID：" + head.getRequestId() + "鑫合直充交易请求异常！", e);
		}
		return resInfo;
	}

	private Map<String, String> assembleParameterOfTrade(
			SLSHttpInterfaceInfo info, String originalGoodsId, String orderId,
			String mechantIP) {
		Map<String, String> pMap = new HashMap<String, String>();
		String md5key = PropertiesUtil.getValue("xinhe.md5.key", filename);
		// 工号
		String merchantId = PropertiesUtil.getValue("xinhe.merchant.id",
				filename);
		pMap.put("orderNo", orderId);
		pMap.put("userId", merchantId);
		pMap.put("productId", originalGoodsId);
		pMap.put("chargeIp", mechantIP);
		String returnUrl = PropertiesUtil
				.getValue("xinhe.return.url", filename);
		pMap.put("notifyUrl", returnUrl);
		String gameArea = info.getGameArea();
		String gameServer = info.getGameServer();
		String accountTypeName = info.getAccountTypeName();
		String buyNum = info.getBuyNum();
		String gameAccount = info.getGameAccount();

		pMap.put("gameAccount", gameAccount);

		String gameId = "";
		String companyId = "";
		String accountTypeId = "";
		String gameZoneId = "";
		String gameServerId = "";
		String parvalue = "";

		XinHeProduct xhp = this.productDao.queryByProductId(originalGoodsId);
		if (xhp != null) {
			companyId = xhp.getCompanyId();
			parvalue = xhp.getProductParvalue();
		}
		pMap.put("buynum", buyNum);

		int amount = 0;
		try {
			int bn = Integer.parseInt(buyNum);
			int par = Integer.parseInt(parvalue);
			amount = bn * par;
		} catch (Exception e) {
			log.error("格式转换异常", e);
		}

		pMap.put("amount", String.valueOf(amount));

		List<XinHeGame> gameList = this.gameDao.queryAllGame(companyId);
		if (gameList != null && !gameList.isEmpty()) {
			gameId = gameList.get(0).getGameId();
		}
		pMap.put("gameId", gameId);
		if (StringUtils.isNotBlank(accountTypeName)) {
			XinHeAccount xa = new XinHeAccount();
			xa.setAccountName(accountTypeName);
			xa.setCompanyId(companyId);
			XinHeAccount xha = this.accountDao.queryByAccountName(xa);
			if (xha != null) {
				accountTypeId = xha.getAccountId();
			}
		}
		if (StringUtils.isNotBlank(gameArea)
				|| StringUtils.isNotBlank(gameServer)) {
			XinHeGame game = new XinHeGame();
			game.setAreaName(gameArea);
			game.setServerName(gameServer);
			game.setCompanyId(companyId);
			game.setGameId(gameId);
			List<XinHeGame> games = this.gameDao
					.queryByAreaNameOrServerName(game);
			if (games != null && !games.isEmpty()) {
				XinHeGame xgame = games.get(0);
				gameZoneId = xgame.getAreaId();
				gameServerId = xgame.getServerId();
			}
		}

		XinHeGameGift gift = new XinHeGameGift();
		gift.setGameId(gameId);
		gift.setCompanyId(companyId);
		List<XinHeGameGift> giftList = this.giftDao.queryGiftByCidAndGid(gift);
		String giftId = "";
		if (giftList != null && !giftList.isEmpty()) {
			XinHeGameGift xgift = giftList.get(0);
			giftId = xgift.getGiftId();
		}
		XinHeChargeUnit xcu = new XinHeChargeUnit();
		xcu.setCompanyId(companyId);
		xcu.setGameId(gameId);
		List<XinHeChargeUnit> cuList = this.chargeDao.queryGiftByCidAndGid(xcu);
		String chargeUnitId = "";
		if (cuList != null && !cuList.isEmpty()) {
			XinHeChargeUnit xhcu = cuList.get(0);
			chargeUnitId = xhcu.getChargeId();
		}

		if (StringUtils.isNotBlank(accountTypeId)) {
			pMap.put("accountTypeId", accountTypeId);
		}
		if (StringUtils.isNotBlank(gameZoneId)) {
			pMap.put("gameZoneId", gameZoneId);
		}
		if (StringUtils.isNotBlank(gameServerId)) {
			pMap.put("gameServerId", gameServerId);
		}
		if (StringUtils.isNotBlank(giftId)) {
			pMap.put("giftId", giftId);
		}
		if (StringUtils.isNotBlank(chargeUnitId)) {
			pMap.put("chargeUnitId", chargeUnitId);
		}

		String sign = createSign(accountTypeId, amount, buyNum, mechantIP,
				chargeUnitId, gameAccount, gameId, gameServerId, gameZoneId,
				giftId, returnUrl, orderId, originalGoodsId, merchantId, md5key);
		pMap.put("sign", sign);
		return pMap;
	}

	private String createSign(String accountTypeId, int amount, String buynum,
			String chargeIp, String chargeUnitId, String gameAccount,
			String gameId, String gameServerId, String gameZoneId,
			String giftId, String notifyUrl, String orderNo, String productId,
			String userId, String md5key) {
		TreeMap<String, Object> treeMap = new TreeMap<String, Object>(
				new Comparator<String>() {
					public int compare(String o1, String o2) {
						return o1.compareTo(o2);
					}
				});
		treeMap.put("accountTypeId", accountTypeId);
		treeMap.put("amount", amount);
		treeMap.put("buynum", buynum);
		treeMap.put("chargeIp", chargeIp);
		treeMap.put("chargeUnitId", chargeUnitId);
		treeMap.put("gameAccount", gameAccount);
		treeMap.put("gameId", gameId);
		treeMap.put("gameServerId", gameServerId);
		treeMap.put("gameZoneId", gameZoneId);
		treeMap.put("giftId", giftId);
		treeMap.put("notifyUrl", notifyUrl);
		treeMap.put("orderNo", orderNo);
		treeMap.put("productId", productId);
		treeMap.put("userId", userId);

		StringBuilder sbu = new StringBuilder();
		Set<Map.Entry<String, Object>> set = treeMap.entrySet();
		Iterator<Map.Entry<String, Object>> it = set.iterator();
		Map.Entry<String, Object> entry = null;
		while (it.hasNext()) {
			entry = it.next();
			if (entry.getValue() != null) {
				if (StringUtils.isNotBlank(entry.getValue().toString())) {
					sbu.append(entry.getValue().toString());
				}
			}
		}
		sbu.append(md5key);
		String data = sbu.toString();
		String sign = UtilMD5Encryption.createMD5Encryption(data);

		return sign;
	}

	private static Map<String, String> map = new HashMap<String, String>();

	static {
		map.put("000", "成功");
		map.put("010", "充值中,表示已接受充值请求,将异步返回充值结果");
		map.put("001", "失败");
		map.put("002", "游戏区不存在");
		map.put("003", "游戏服务器不存在");
		map.put("006", "充值产品类型不存在");
		map.put("007", "游戏类型不存在");
		map.put("008", "游戏卡密错误");
		map.put("009", "流水号不存在");
		map.put("011", "IP错误");
		map.put("012", "库存不足");
		map.put("013", "玩家帐号不存在");
		map.put("014", "玩家帐号状态异常");
		map.put("015", "角色不存在");
		map.put("016", "角色信息异常");
		map.put("017", "经销商储值帐号不存在");
		map.put("018", "经销储值帐号被禁用");
		map.put("019", "经销商储值帐号余额不足");
		map.put("020", "游戏厂商异常");
		map.put("021", "游戏厂商关闭");
		map.put("100", "重复提交");
		map.put("403", "请求超时");
		map.put("500", "未知错误");
		map.put("501", "参数错误");
		map.put("502", "数字签名错误");
		map.put("555", "此功能暂时不可用，系统维护中");
	}
}
